package com.young.ysepay.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.aliyun.openservices.ons.api.Message;
import com.aliyun.openservices.ons.api.Producer;
import com.young.ysepay.dto.YsPayDTO;
import com.young.ysepay.mq.YsReturnMQConfig;
import com.young.ysepay.service.YsAlipayService;
import com.young.ysepay.service.YsBuildRequestParaService;
import com.young.ysepay.service.YsBusinessPramService;
import com.young.ysepay.service.YsVerifyJsonSignService;
import com.young.ysepay.utils.DateFormatHelper;
import com.young.ysepay.utils.DateUtil;
import com.young.ysepay.utils.Https;
import com.young.ysepay.utils.ReturnUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
public class YsAlipayServiceImpl implements YsAlipayService{

    private static Logger logger = LoggerFactory.getLogger(YsAlipayServiceImpl.class);

    @Autowired
    private YsBusinessPramService ysBusinessPramService;
    @Autowired
    private YsBuildRequestParaService ysBuildRequestParaService;
    @Autowired
    private YsVerifyJsonSignService ysVerifyJsonSignService;
    @Value("${AliPayNotifyUrl}")
    private String aliPayNotifyUrl;
    @Autowired
    Producer producer;
    private static  String method="ysepay.online.alijsapi.pay";
    @Override
    public Map<String, Object> ysAliPay(Map<String, String> param) {

        //交易标题
        String subject = param.get("subject");
        //交易金额
        String totalAmount = param.get("total_amount");
        //平台订单号
        String outTradeNo = param.get("out_trade_no");
        //支付宝用户Id
        String buyerId = param.get("buyer_id");
        logger.info("调用银盛支付宝支付参数：支付交易标题:{},交易金额:{},第三方支付单号:{}",subject,totalAmount,outTradeNo);
        if(StringUtils.isEmpty(subject) || StringUtils.isEmpty(totalAmount)
                || StringUtils.isEmpty(outTradeNo) || StringUtils.isEmpty(buyerId)){
            return ReturnUtils.paramIsNull();
        }
        Map<String,String> map = new HashMap<>();
        //获取签名组件
        YsPayDTO ysPayDTO = ysBusinessPramService.ysBusinessPram();
        map.put("method",method);
        map.put("partner_id",ysPayDTO.getPARTNER_ID());
        map.put("timestamp", DateFormatHelper.getNowTimeStr());
        map.put("charset",ysPayDTO.getDEFAULT_CHARSET());
        map.put("sign_type",ysPayDTO.getSIGN_ALGORITHM());
        map.put("notify_url",aliPayNotifyUrl);
        map.put("version",ysPayDTO.getVERSION());
        Map<String,Object> biz_content = new HashMap<>();
        biz_content.put("out_trade_no",outTradeNo);
        biz_content.put("shopdate", DateUtil.getDateFormat(new Date(),DateUtil.simple));
        biz_content.put("subject",subject);
        biz_content.put("total_amount",totalAmount);
        biz_content.put("seller_id",ysPayDTO.getPARTNER_ID());
        biz_content.put("seller_name",ysPayDTO.getSELLER_NAME());
        biz_content.put("timeout_express",ysPayDTO.getTIMEOUT_EXPRESS());
        biz_content.put("business_code",ysPayDTO.getBUSINESS_CODE());
        biz_content.put("buyer_id",buyerId);
//        String payChannelFee = new BigDecimal(totalAmount).multiply(new BigDecimal("0.0045")).setScale(2, RoundingMode.HALF_UP).toEngineeringString();
//        biz_content.put("mer_amount",payChannelFee);
        map.put("biz_content", JSON.toJSONString(biz_content));
        Map<String,Object> realResponse = new HashMap<>();
        try {
            //签名
            Map<String, String> para = ysBuildRequestParaService.buildRequestPara(map);
            logger.info("银盛支付宝支付请求发起签名{}",para);
            //发起请求
            String retuenMessage = Https.httpsSend(ysPayDTO.getYSEPAY_GATEWAY_URL(), para);
            logger.info("银盛支付宝支付返回请求参数{}",retuenMessage);
            //json转map
            Map<String, Object> response = (Map<String, Object>) JSON.parse(retuenMessage);
            //返回消息属性
            Map<String, Object> aliAccept = (Map<String, Object>)response.get("ysepay_online_alijsapi_pay_response");
            logger.info("银盛支付宝支付预支付信息返回{}",aliAccept);
            String sign = response.get("sign").toString();
            realResponse.putAll(aliAccept);
            realResponse.put("sign",sign);
            int begin = retuenMessage.indexOf("ysepay_online_alijsapi_pay_response");
            String substring = retuenMessage.substring(begin);
            substring= substring.replace("ysepay_online_alijsapi_pay_response","");
            substring = substring.substring(2,substring.length()-1);
            boolean verifyResult = ysVerifyJsonSignService.verifyJsonSign(sign, substring, "utf-8");
            realResponse.put("verifyResult",verifyResult);
            return realResponse;
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            return realResponse;
        }
    }

    @Override
    public void aliPayCallBack(Map<String, String> params, HttpServletResponse response) {

        PrintWriter printWriter = null;

        logger.info("请求参数"+params);
        try {
            printWriter = response.getWriter();
            boolean flag = ysVerifyJsonSignService.verifySign(params);
            logger.info("银盛支付宝异步回执签名验证情况"+flag);
            if(flag == true){
                String msg = JSON.toJSONString(params, SerializerFeature.DisableCircularReferenceDetect);
                Message message = new Message(YsReturnMQConfig.PAYTOPIC,YsReturnMQConfig.YS_ALI_PAY_TAG,msg.getBytes());
                producer.send(message);
                logger.info("银盛支付宝异步发往支付中心消息{}",message);
                logger.info("同步返回银盛异步接口通知应答","success");
                printWriter.println("success");
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        }finally {
            if(printWriter != null){
                printWriter.close();
            }
        }
    }

}
